package org.realogic.cfm.persistence.jdbc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import org.realogic.cfm.domain.KPageResult;
import org.realogic.cfm.persistence.KParameter;
import org.realogic.cfm.persistence.dialect.Dialect;

public class KJdbcDivPageQueryer<T> {

	private Dialect dialect;

	private Connection dbConnection;

	private String sql;

	private List<KParameter> paramters;

	private int pageNo;

	private int pageSize;

	private KRowGetter<T> converter;

	public KJdbcDivPageQueryer(Dialect dialect_, Connection dbConnection_, String sql_, List<KParameter> paramters_, int pageNo_, int pageSize_, KRowGetter<T> converter_) {
		this.dialect = dialect_;
		this.dbConnection = dbConnection_;
		this.sql = sql_;
		this.paramters = paramters_;
		this.pageNo = pageNo_;
		this.pageSize = pageSize_;
		this.converter = converter_;
	}

	public KPageResult<T> query() throws SQLException {
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		KPageResult<T> tmp = null;
		int totalSize = 0; // 总记录数
		try {
			// 获取总记录数
			totalSize = queryTotalSize();
			if (totalSize > 0) {
				String tmpSql = dialect.getLimitString(sql, pageNo, pageSize);
				pstmt = dbConnection.prepareStatement(tmpSql, java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY);
				List<T> tmpList = null;
				List<KParameter> tmpNewParameters = null;
				int size = 0;
				if (paramters != null) {
					tmpNewParameters = dialect.newDivPageParameters(paramters);
					size = tmpNewParameters.size();
				}
				KParameter tmpParam = null;
				for (int i = 0; i < size; i++) {
					tmpParam = tmpNewParameters.get(i);
					tmpParam.fillPreparedStatement(pstmt, i + 1);
				}
				// 执行查询
				rs = pstmt.executeQuery();
				try {
					if (pageSize > 10000) {
						rs.setFetchSize(100);
					} else {
						rs.setFetchSize(pageSize);
					}
				} catch (SQLException ee) {

				}
				tmpList = new ArrayList<T>(pageSize > 0 ? pageSize : 10);
				while (rs.next()) {
					tmpList.add(converter.convertResultSet(rs));
				}
				tmp = new KPageResult<T>(tmpList, totalSize, pageNo, pageSize);
			}
		} catch (SQLException e) {
			throw e;
		} finally {
			close(pstmt, rs);
		}
		return tmp;
	}

	private int queryTotalSize() throws SQLException {
		int value = 0;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		try {
			pstmt = dbConnection.prepareStatement(dialect.getCountSQL(sql), java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY);
			int size = 0;
			if (paramters != null) {
				size = paramters.size();
			}
			KParameter tmpParam = null;
			for (int i = 0; i < size; i++) {
				tmpParam = paramters.get(i);
				tmpParam.fillPreparedStatement(pstmt, i + 1);
			}
			// 执行查询
			rs = pstmt.executeQuery();
			if (rs.next()) {
				value = rs.getInt(1);
			}
		} catch (SQLException e) {
			throw e;
		} finally {
			close(pstmt, rs);
		}
		return value;
	}

	private void close(Statement statement, ResultSet rs) {
		try {
			if (rs != null) {
				rs.close();
			}
		} catch (SQLException e) {
		}
		rs = null;
		try {
			if (statement != null) {
				statement.close();
			}
		} catch (SQLException e) {
		}
		statement = null;
	}
}